be->dev = dev;
be->backend_watch.node = dev->nodename;
be->backend_watch.callback = backend_changed;
+ /* Will implicitly call backend_changed once. */
err = register_xenbus_watch(&be->backend_watch);
if (err) {
be->backend_watch.node = NULL;
}
dev->data = be;
-
- backend_changed(&be->backend_watch, dev->nodename);
return 0;
free_be:
be->dev = dev;
be->backend_watch.node = dev->nodename;
be->backend_watch.callback = backend_changed;
+ /* Registration implicitly fires backend_changed once */
err = register_xenbus_watch(&be->backend_watch);
if (err) {
be->backend_watch.node = NULL;
}
dev->data = be;
-
- backend_changed(&be->backend_watch, dev->nodename);
return 0;
free_be:
be->dev = dev;
be->backend_watch.node = dev->nodename;
be->backend_watch.callback = backend_changed;
+ /* Registration implicitly calls backend_changed. */
err = register_xenbus_watch(&be->backend_watch);
if (err) {
be->backend_watch.node = NULL;
}
dev->data = be;
-
- backend_changed(&be->backend_watch, dev->nodename);
return 0;
free_be:
return err;
}
-
- /* Call once in case entries already there. */
- watch_for_status(&info->watch, info->watch.node);
-
return 0;
}
be->dev = dev;
be->backend_watch.node = dev->nodename;
+ /* Implicitly calls backend_changed() once. */
be->backend_watch.callback = backend_changed;
be->instance = -1;
err = register_xenbus_watch(&be->backend_watch);
}
dev->data = be;
-
- backend_changed(&be->backend_watch, dev->nodename);
return err;
free_be:
return err;
}
- watch_for_status(&info->watch, info->watch.node);
return 0;
}
# Watch event must have happened before we registered interest.
1 watch / token
2 write /test/subnode contents2
-1 watch / token2 0
+1 watchnoack / token2 0
expect 1:/test/subnode:token
1 waitwatch
1 ackwatch token
+expect 1:/:token2
+1 waitwatch
expect 1: waitwatch failed: Connection timed out
1 waitwatch
1 close
getperm /dir/file
expect *Permission denied
setperm /dir/file 0 NONE
-watch /dir/file token
+# We get no watch event when there's no permission. It's a corner case.
+watchnoack /dir/file token
1 write /dir/file contents
1 rm /dir/file
expect waitwatch failed: Connection timed out
getperm /dir/file
expect *Permission denied
setperm /dir/file 0 NONE
-watch /dir/file token
+watchnoack /dir/file token
1 write /dir/file contents
1 rm /dir/file
expect waitwatch failed: Connection timed out
trace_create(watch, "watch");
talloc_set_destructor(watch, destroy_watch);
send_ack(conn, XS_WATCH);
+
+ /* We fire once up front: simplifies clients and restart. */
+ add_event(conn, watch, watch->node);
}
void do_watch_ack(struct connection *conn, const char *token)
" setperm <path> <id> <flags> ...\n"
" shutdown\n"
" watch <path> <token>\n"
+ " watchnoack <path> <token>\n"
" waitwatch\n"
" ackwatch <token>\n"
" unwatch <path> <token>\n"
failed(handle);
}
-static void do_watch(unsigned int handle, const char *node, const char *token)
+static void do_watch(unsigned int handle, const char *node, const char *token,
+ bool swallow_event)
{
if (!xs_watch(handles[handle], node, token))
failed(handle);
+
+ /* Convenient for testing... */
+ if (swallow_event) {
+ char **vec = xs_read_watch(handles[handle]);
+ if (!vec || !streq(vec[0], node) || !streq(vec[1], token))
+ failed(handle);
+ if (!xs_acknowledge_watch(handles[handle], token))
+ failed(handle);
+ }
}
static void set_timeout(void)
else if (streq(command, "shutdown"))
do_shutdown(handle);
else if (streq(command, "watch"))
- do_watch(handle, arg(line, 1), arg(line, 2));
+ do_watch(handle, arg(line, 1), arg(line, 2), true);
+ else if (streq(command, "watchnoack"))
+ do_watch(handle, arg(line, 1), arg(line, 2), false);
else if (streq(command, "waitwatch"))
do_waitwatch(handle);
else if (streq(command, "ackwatch"))